using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace Win32SDK
{
    public sealed class GDI32
    {
        public const string Dll = "gdi32.Dll";
        private GDI32()
        {

        }

        [DllImport(GDI32.Dll, CharSet = CharSet.Auto)]
        public static extern bool TextOut(IntPtr hdc, int nXStart, int nYStart, string lpString, int cbString);
        [DllImport(GDI32.Dll, CharSet = CharSet.Auto)]
        public static extern int SetBkMode(IntPtr hdc, int iBkMode);

        [DllImport(GDI32.Dll, EntryPoint = "DeleteDC", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        private static extern bool IntDeleteDC(HandleRef hDC);
        [DllImport(GDI32.Dll, EntryPoint = "CreateCompatibleDC", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        private static extern IntPtr IntCreateCompatibleDC(HandleRef hDC);
        [DllImport(GDI32.Dll, EntryPoint = "CreateDC", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr IntCreateDC(string lpszDriver, string lpszDeviceName, string lpszOutput, HandleRef devMode);
        [DllImport(GDI32.Dll, EntryPoint = "CreateIC", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr IntCreateIC(string lpszDriverName, string lpszDeviceName, string lpszOutput, HandleRef lpInitData);
        [DllImport(GDI32.Dll, CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        public static extern IntPtr GetStockObject(int nIndex);

        [DllImport(GDI32.Dll, CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        public static extern int GetRegionData(HandleRef hRgn, int size, IntPtr lpRgnData);
        [DllImport(GDI32.Dll, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int GetObject(HandleRef hObject, int nSize, ref int nEntries);
        [DllImport(GDI32.Dll, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int GetObject(HandleRef hObject, int nSize, [In, Out] BITMAP bm);
        [DllImport(GDI32.Dll, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int GetObject(HandleRef hObject, int nSize, [In, Out] LOGPEN lp);
        [DllImport(GDI32.Dll, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int GetObject(HandleRef hObject, int nSize, int[] nEntries);
        [DllImport(GDI32.Dll, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int GetObject(HandleRef hObject, int nSize, [In, Out] LOGBRUSH lb);
        [DllImport(GDI32.Dll, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int GetObject(HandleRef hObject, int nSize, [In, Out] LOGFONT lf);
        [DllImport(GDI32.Dll, CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        public static extern int GetObjectType(HandleRef hObject);
        [DllImport(GDI32.Dll, CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        public static extern int GetDeviceCaps(HandleRef hDC, int nIndex);

        public static IntPtr CreateCompatibleDC(HandleRef hDC)
        {
            return HandleCollector.Add(IntCreateCompatibleDC(hDC), CommonHandles.CompatibleHDC);
        }

        public static IntPtr CreateDC(string lpszDriver)
        {
            return HandleCollector.Add(IntCreateDC(lpszDriver, null, null,Constants.NullHandleRef), CommonHandles.HDC);
        }

        public static IntPtr CreateDC(string lpszDriverName, string lpszDeviceName, string lpszOutput, HandleRef lpInitData)
        {
            return HandleCollector.Add(IntCreateDC(lpszDriverName, lpszDeviceName, lpszOutput, lpInitData), CommonHandles.HDC);
        }

        public static IntPtr CreateIC(string lpszDriverName, string lpszDeviceName, string lpszOutput, HandleRef lpInitData)
        {
            return HandleCollector.Add(IntCreateIC(lpszDriverName, lpszDeviceName, lpszOutput, lpInitData), CommonHandles.HDC);
        }

        public static int GetObject(HandleRef hObject, LOGBRUSH lb)
        {
            return GetObject(hObject, Marshal.SizeOf(typeof(LOGBRUSH)), lb);
        }

        public static int GetObject(HandleRef hObject, LOGFONT lp)
        {
            return GetObject(hObject, Marshal.SizeOf(typeof(LOGFONT)), lp);
        }
        public static bool DeleteCompatibleDC(HandleRef hDC)
        {
            HandleCollector.Remove((IntPtr)hDC, CommonHandles.CompatibleHDC);
            return IntDeleteDC(hDC);
        }

        public static bool DeleteDC(HandleRef hDC)
        {
            HandleCollector.Remove((IntPtr)hDC, CommonHandles.HDC);
            return IntDeleteDC(hDC);
        }

        public static int GetObject(HandleRef hObject, LOGPEN lp)
        {
            return GetObject(hObject, Marshal.SizeOf(typeof(LOGPEN)), lp);
        }
        public static unsafe RECT[] GetRectsFromRegion(IntPtr hRgn)
        {
            RECT[] rectArray = null;
            IntPtr zero = IntPtr.Zero;
            try
            {
                int cb = GetRegionData(new HandleRef(null, hRgn), 0, IntPtr.Zero);
                if (cb == 0)
                {
                    return rectArray;
                }
                zero = Marshal.AllocCoTaskMem(cb);
                if (GetRegionData(new HandleRef(null, hRgn), cb, zero) != cb)
                {
                    return rectArray;
                }
                RGNDATAHEADER* rgndataheaderPtr = (RGNDATAHEADER*)zero;
                if (rgndataheaderPtr->iType != 1)
                {
                    return rectArray;
                }
                rectArray = new RECT[rgndataheaderPtr->nCount];
                int cbSizeOfStruct = rgndataheaderPtr->cbSizeOfStruct;
                for (int i = 0; i < rgndataheaderPtr->nCount; i++)
                {
                    rectArray[i] = ((RECT*)((byte*)zero) + cbSizeOfStruct)[i];
                }
            }
            finally
            {
                if (zero != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(zero);
                }
            }
            return rectArray;
        }


    }
}
